package gamePlay;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import netcode.client.Client;
import netcode.helper.ClientMessageListener;
import netcode.helper.NetcodeHelper;

public class MultiPlayerTest implements ClientMessageListener {
	private Game game;
	private Client client;
	private String name;
	private boolean serverLobbyInfoReceived = false;
	private boolean gameLobbyInfoReceived = false;
	private boolean questionReceived = false;
	private boolean bettingOddsReceived = false;
	private boolean roundResultsReceived = false;
	private boolean endOfGameReceived = false;

	public static void main(String args[]) {
		MultiPlayerTest test = new MultiPlayerTest();
		test.begin();
	}

	public void begin() {
		name = getNameFromUser();
		game = new Game();
		try {
			client = new Client(NetcodeHelper.SERVER_ADDRESS,
					NetcodeHelper.SERVER_PORT, name, game);
			client.setListener(this);
			// This is an important part.
			client.start();
			client.sendConnectionRequest();
			Scanner keyboard = new Scanner(System.in);
			int option = 0;
			do {
				displayMainMenu();
				System.out.print("Please enter your choice:");
				option = keyboard.nextInt();
				switch (option) {
				case 1:
					printServerLobby();
					break;
				case 2:
					createGame();
					break;
				case 3:
					joinGame();
					break;
				case 4:
					disconnect();
					break;
				}
			} while (option != 4);
		} catch (Exception e) {
			System.err.println(e);
		}
	}

	public void printServerLobby() {
		serverLobbyInfoReceived = false;
		do {
			client.sendServerLobbyInfoRequest();
			sleepyTime();
		} while (!serverLobbyInfoReceived);
		
		// Clean this up once Lobby is fully implemented
		System.out.println(client.getLobby());

	}

	public void createGame() {
		Scanner keyboard = new Scanner(System.in);
		System.out.print("Please input a game name: ");
		String name = keyboard.nextLine();
		client.sendCreateGameRequest(name, 7, new String[] {});
		hostGameLobby();
	}

	public void joinGame() {
		Scanner keyboard = new Scanner(System.in);
		System.out.print("Please input the gameId: ");
		int gameId = keyboard.nextInt();
		gameLobbyInfoReceived = false;
		do {
			client.sendJoinGameRequest(gameId);
			sleepyTime();
		} while (!gameLobbyInfoReceived);
		clientGameLobby();
	}

	public String getNameFromUser() {
		Scanner keyboard = new Scanner(System.in);
		System.out.print("Please input your name: ");
		String name = keyboard.nextLine();
		return name;
	}

	public void displayMainMenu() {
		System.out.println("*******Main Menu*******");
		System.out.println("1. Print Server Lobby");
		System.out.println("2. Create Game");
		System.out.println("3. Join Game");
		System.out.println("4. Quit");
	}

	public void displayHostGameMenu() {
		System.out.println("*******Game Menu*******");
		System.out.println("1. Print Game Lobby");
		System.out.println("2. Start Game");
		System.out.println("3. Leave Game");
	}
	
	public void displayClientGameMenu(){
		System.out.println("*******Game Menu*******");
		System.out.println("1. Print Game Lobby");
		System.out.println("2. Wait for Game to Start");
		System.out.println("3. Leave Game");
	}

	public void hostGameLobby() {
		int option = 0;
		Scanner keyboard = new Scanner(System.in);
		do {
			displayHostGameMenu();
			System.out.print("Please input your selection: ");
			option = keyboard.nextInt();
			switch (option) {
			case 1:
				printGameLobby();
				break;
			case 2:
				hostStartGame();
				break;
			case 3:
				leaveGame();
				break;
			}
		} while (option != 3);
	}
	
	public void clientGameLobby(){
		int option = 0;
		Scanner keyboard = new Scanner(System.in);
		do {
			displayClientGameMenu();
			System.out.print("Please input your selection: ");
			option = keyboard.nextInt();
			switch (option) {
			case 1:
				printGameLobby();
				break;
			case 2:
				clientStartGame();
				break;
			case 3:
				leaveGame();
				break;
			}
		} while (option != 3);
	}

	public void disconnect() {
		client.sendDisconnect();
	}

	public void leaveGame() {
		client.sendLeaveGameRequest(game.getGameID());
	}

	public void hostStartGame(){
		questionReceived = false;
		do {
			client.sendStartGameRequest(game.getGameID());
			sleepyTime();
		} while (!questionReceived);
		startGame();
	}
	
	public void clientStartGame(){
		do {
			sleepyTime();
		} while (!questionReceived);
		startGame();
	}
	
	public void startGame() {
		Scanner keyboard = new Scanner(System.in);
		int choice = 0;
		
		//questionReceived = false;
		do {
			questionReceived = false;
			System.out.println(game.getQuestion().getText());
			//game.displayQuestion();
			System.out.print("Please Input your answer: ");
			int answer = keyboard.nextInt();
			client.sendAnswer(game.getGameID(), answer);
			System.out.println("Waiting for other players...");
			do {
				sleepyTime();
			} while (!bettingOddsReceived);
			bettingOddsReceived = false;
			List<Guess> guesses = game.getGuesses();
			System.out.println("***Guesses and Odds***");
			for(int i = 0; i < guesses.size(); i++){
				System.out.println("Guess " + i + ": " + guesses.get(i).getGuess() + " Odds: " + guesses.get(i).getOdds());
			}
			List<Bet> bets = getPlayerBets(game.getGuesses());
	System.out.println(bets);
			client.sendSubmitBets(bets, game.getGameID());
			System.out.println("Waiting for other players...");
			do {
				sleepyTime();
			} while (!roundResultsReceived);
			roundResultsReceived = false;
			System.out
					.println("***Round Results***");
			System.out.println("The correct answer was: " + game.getQuestion().getAnswer());
			for(int i = 0; i < game.getPlayers().size(); i++){
				System.out.println(game.getPlayers().get(i).getPlayer_name() + " now has " + game.getPlayers().get(i).getGame_chips() + " game chips.");
			}

			do {
				System.out.println("1. Continue to the next round");
				System.out.println("2. Leave Game");
				System.out.print("Please enter your selection: ");
				choice = keyboard.nextInt();
			} while (choice < 1 || choice > 2);
			if (choice == 1) {
				client.sendNextRoundRequest(game.getGameID());
			} else if (choice == 2) {
				leaveGame();
				break;
			}
			do {
				sleepyTime();
			} while (!questionReceived && !endOfGameReceived);
		} while (!endOfGameReceived);
		endOfGameReceived = false;
		System.out.println("Print the end of game results here!");

	}

	public void printGameLobby() {
		for (int i = 0; i < game.getPlayers().size(); i++) {
			System.out.println("*****Players*****");
			System.out.println(game.getPlayers().get(i).getPlayer_name());
		}
	}

	private List<Bet> getPlayerBets(List<Guess> guesses) {
		Scanner keyboard = new Scanner(System.in);
		List<Bet> bets = new ArrayList<Bet>();
		int choice = -1;
		int permaChips = 0;
		int tempChips = 0;
		System.out.println("Place your bets now.");
		do {
			System.out
					.print("On which guess do you wish to place a bet(-1 to end betting): ");
			choice = keyboard.nextInt();
			if (choice >= 0 && choice < guesses.size()) {
				System.out
						.print("How many permanent chips would you like to bet: ");
				permaChips = keyboard.nextInt();
				System.out
						.print("How many temporary chips would you like to bet: ");
				tempChips = keyboard.nextInt();
				/* Changed to work with new bet format - Jim J */
				bets.add(new Bet(name, choice, permaChips, tempChips));
			}
		} while (choice != -1);
		System.out.println();
		return bets;
	}

	@Override
	public void onMessageReceived(byte packetCode) {
			System.out.println("onMessageReceived() entered with code: " + packetCode);
		switch (packetCode) {
		case NetcodeHelper.SERVER_LOBBY_INFO_RESPONSE:
			serverLobbyInfoReceived = true;
			break;
		case NetcodeHelper.GAME_LOBBY_INFO:
			gameLobbyInfoReceived = true;
			break;
		case NetcodeHelper.QUESTION:
			questionReceived = true;
			break;
		case NetcodeHelper.BETTING_ODDS:
			bettingOddsReceived = true;
			break;
		case NetcodeHelper.ROUND_RESULTS:
			roundResultsReceived = true;
			break;
		case NetcodeHelper.GAME_RESULTS:
			endOfGameReceived = true;
			break;
		}

	}

	/**
	 * Waits for some time so that a message has time to be received.
	 */
	public void sleepyTime() {
		try {
			Thread.sleep(NetcodeHelper.MILLISECONDS_BETWEEN_SENDING_MESSAGE);
		} catch (Exception e) {
			System.err.println(e);
		}
	}
}
